package org.liuwei.concucrent.base03.HashMap10;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMap01 {
	private final Map<String, Long> wordCounts = new ConcurrentHashMap<String, Long>();

	/* 举个例子：统计文本中单词出现的次数，把单词出现的次数记录到一个Map中，代码如下： */
	public long increase(String word) {
		Long oldValue = wordCounts.get(word);
		Long newValue = (oldValue == null) ? 1L : oldValue + 1;
		wordCounts.put(word, newValue);
		
		return newValue;
	}

	/*
	 * 如果多个线程并发调用这个increase()方法，increase()的实现就是错误的，
	 * 因为多个线程用相同的word调用时，很可能会覆盖相互的结果，造成记录的次数比实际出现的次数少。
	 * 除了用锁解决这个问题，另外一个选择是使用ConcurrentMap接口定义的方法：
	 */

	/*
	 * 这是个被很多人忽略的接口，也经常见有人错误地使用这个接口。ConcurrentMap接口定义了几个基于 CAS（Compare and
	 * Set）操作，很简单，但非常有用， 下面的代码用ConcurrentMap解决上面问题：
	 */
	public long increase2(String word) {
		Long oldValue, newValue;
		while (true) {
			oldValue = wordCounts.get(word);
			if (oldValue == null) {
				// Add the word firstly, initial the value as 1
				newValue = 1L;
				if (wordCounts.putIfAbsent(word, newValue) == null) {
					break;
				}
			} else {
				newValue = oldValue + 1;
				if (wordCounts.replace(word, oldValue, newValue)) {
					break;
				}
			}
		}
		return newValue;
	}
}
